
#include <glf/core/str.h>
#include <glf/core/inlines.h>

#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>

namespace glf { 

struct Fs::Impl : public FsImplBase{
	Impl(Fs& fs) :
		FsImplBase(fs) {
	}
	virtual ~Impl() {
	}

	bool RemoveFile(const char* file) {
		return unlink(file) == 0;
	}

	bool DoesFileExist(const char* path) {
		struct stat stFileInfo; 
		int intStat; 

		intStat = stat(path,&stFileInfo); 
		return intStat == 0;
	}

	bool MkDir(const char* dir, openflag flag) {
		return mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) == 0;
	}

	bool Init(const char* dataRoot) {
		return true;
	}


	virtual void GetCwd(int size, char* buffer) {
		getcwd(buffer, size);
	}

	virtual void SetCwd(const char* cwd) {
		chdir(cwd);
	}

};

namespace fs {

//dont know the exact max path
#define KD_MAX_PATH 260


struct DirHandle::Impl {
	DirHandle& mDirHandle;
	DIR* mHandle;
	std::string mPath;//to track in which path we are searching
	openflag mFlag;
	char mSearchExt[8];
	
	Impl(DirHandle& dirHandle) :
		mDirHandle(dirHandle) {
		mHandle = 0;
		//getApplicationPath(mRoot); 
	}
	~Impl() {
		Close();
	}

	bool FindFirst(const char* filename, openflag flag, FileInfo& fi) {
		Close();

		mPath = filename;

		mFlag = flag;
		
		mHandle = opendir(mPath.c_str());

		if(mHandle) {
			return FindNext(fi);
		} else {
			mDirHandle.mLastError = ERROR_NOEXISTS;
			return false;
		}
	}

	bool FindNext(FileInfo& fi) {
		dirent* dirent = readdir(mHandle);
		fi.fullpath.clear();

		if(dirent)
		{
			struct stat info;
			fi.fullpath = JoinPath(mPath.c_str(), dirent->d_name);

			stat(fi.fullpath.c_str(), &info);
			
			fi.isDir = S_ISDIR(info.st_mode) ;

			fi.filename = dirent->d_name;
			fi.size = info.st_size;
			fi.timeLastModified = info.st_mtime;
			fi.timeLastAccessed = info.st_atime;

			return true;
		}

		return false;
	}

	void Close() {
		if(mHandle) {
			closedir(mHandle);
			mHandle = 0;
		}
	}
};

} //namespace fs
} //namespace glf

